package cn.cnooc.service;

import cn.cnooc.config.InfluxDbComUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class HistoryDataService {

    @Autowired
    private InfluxDbComUtil influxDbComUtil;
    private static final String xDataName = "xData";
    private static final String yDataName = "yData";
    private static final String QUERY_STATISTICS = "select sum(difference) as num from ( select DIFFERENCE({}) from  {} where time >'{}'  and time <'{}'  tz('Asia/Shanghai')) ";
    private static final String QUERY_INSTANTANEOUS_DATA = "SELECT mean({}) AS num FROM {} WHERE time >= '{}' AND time < '{}' GROUP BY time(5m) fill(0)  tz('Asia/Shanghai')  ";

    public Map<String, Object> timeCurve(String tableName, String location, Date date, DateField dateField, int maxValue) {
        SimpleDateFormat sdf = DateUtil.newSimpleFormat("yyyy-MM-dd HH:mm:ss");
        Map<String, Object> resultCurve = new HashMap<>();
        List<String> xData = CollUtil.newArrayList();
        List<String> yData = CollUtil.newArrayList();

        for (int i = 0; i < maxValue; i++) {

            xData.add((maxValue==24?i:i+1)+""); //1
            DateTime offset = DateUtil.offset(date, dateField, 1); //2
            if (DateUtil.date(date).isAfter(DateUtil.date())) {
                yData.add("0");
            } else {
                String format1 = StrUtil.format(QUERY_STATISTICS, location, tableName, sdf.format(date), sdf.format(offset));
                List<Map<String, Object>> query = influxDbComUtil.query(format1);
                yData.add(query.isEmpty() ? "0" : NumberUtil.roundStr(query.get(0).get("num").toString(), 2, RoundingMode.CEILING));
            }
            date = DateUtil.offset(date, dateField, 1);
        }
        resultCurve.put(xDataName, xData);
        resultCurve.put(yDataName, yData);
        return resultCurve;
    }


    public Map<String, Object> hourByDayCurve(String tableName, String location) {
        return timeCurve(tableName, location, DateUtil.beginOfDay(DateUtil.date()), DateField.HOUR_OF_DAY, 24);
    }


    public Map<String, Object> dayByMonthCurve(String tableName, String location) {
        return timeCurve(tableName, location, DateUtil.beginOfMonth(DateUtil.date()), DateField.DAY_OF_MONTH, DateUtil.endOfMonth(DateUtil.date()).dayOfMonth());
    }


    public Map<String, Object> monthByYearCurve(String tableName, String location) {
        return timeCurve(tableName, location, DateUtil.beginOfYear(DateUtil.date()), DateField.MONTH, 12);
    }

    public Map<String, List> queryInstantaneousData(String tableName, String location) {
        SimpleDateFormat sdf = DateUtil.newSimpleFormat("yyyy-MM-dd HH:mm:ss");
        Map<String, List> resultMap = new HashMap<>();
        List<String> xData = CollUtil.newArrayList();
        List<String> yData = CollUtil.newArrayList();

        String queryStr
                = StrUtil.format(QUERY_INSTANTANEOUS_DATA, location, tableName, sdf.format(DateUtil.beginOfDay(new Date())), sdf.format(DateUtil.endOfDay(new Date())));

        List<Map<String, Object>> results = influxDbComUtil.query(queryStr);
        for (Map result : results) {
            String time = result.get("time").toString();
            ZonedDateTime zonedDateTime = ZonedDateTime.parse(time, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
            DateTimeFormatter targetFormatter = DateTimeFormatter.ofPattern("HH:mm");
            String format = zonedDateTime.format(targetFormatter);
            xData.add(format);
            yData.add(result.get("num").toString());
        }
        resultMap.put("xData", xData);
        resultMap.put("yData", yData);
        return resultMap;
    }
}
